/*
 * OGLContext.h
 *
 *  Created on: 15 févr. 2011
 *      Author: seeme
 *      Un contexte opengl, ouvre la fenetre et lance
 *      la boucle principale qui va mettre à jour les différents
 *      états de l'application.
 */

#ifndef OGLCONTEXT_H_
#define OGLCONTEXT_H_

#include "AbstractContext.h"
#include <SFML/Window.hpp>
#include "../../Tools/Misc/Singleton.h"
#include "../../Tools/Geometry/Matrix4.h"
#include "../../Memory/Resources/Level/Level.h"
#include "../../Memory/Resources/TextBased/Shaders/Shader.h"
#include "../../Input/UserInputState.h"
#include "../Lights/OmniLight.h"
#include <GL/glew.h>
#include <stack>

class OGLContext: public AbstractContext {
public:
	OGLContext();
	virtual ~OGLContext();

	void render(void);
	void reshape(int width, int height);

	void openContext(int width, int height, const char* title);
	void run();

	void keyPressEvent(unsigned char key, int x, int y);
	void keyUpEvent(unsigned char key, int x, int y);
	void idle();
private:
	sf::Window App;
	GLuint m_program;

	Level* m_currentLvl;

	void loadShaders();

	void drawGizmos();

	void drawGraph(sNode<StaticDrawableEntity*>& node);

	//Les transformations
	Matrix4<float> m_proj, m_view, m_model;
	std::stack<Matrix4<float> > m_matStack;

	void updateMatrices(GLuint program);

	void pushMatrix();
	void popMatrix();

	void lookAt(GLfloat eyeX, GLfloat eyeY, GLfloat eyeZ, GLfloat targetX, GLfloat targetY, GLfloat targetZ, GLfloat upX = 0.0f, GLfloat upY = 1.0f, GLfloat upZ = 0.0f);

	void setPerspective(GLfloat fovY, GLfloat ratio, GLfloat zNear, GLfloat zFar);

	void loadIdentity();

	void translate(GLfloat x, GLfloat y, GLfloat z);
	void rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
	void scale(GLfloat x, GLfloat y, GLfloat z);

	void renderAmbiant(sNode<StaticDrawableEntity*>& node);
	void renderDiffuseLight(sNode<StaticDrawableEntity*>& node);

	void sendEyePos(GLuint program);


	void drawWithVBO()	{
		GLfloat size = 0.5f;
		GLuint mcc_buffers[3];

		GLfloat mcc_tab_vertices[] =
		{
			-size, -size,  size,
			 size, -size,  size,
			-size,  size,  size,
			 size,  size,  size,
			-size, -size, -size,
			 size, -size, -size,
			-size,  size, -size,
			 size,  size, -size
		};

		GLfloat mcc_tab_colors[] =
		{
			1,0,0,
			0,1,0,
			0,0,1,
			0,1,1,
			1,0,0,
			0,1,0,
			0,0,1,
			0,1,1
		};

		GLuint mcc_tab_indices[] =
		{
			0, 1, 2, 3, 7, 1, 5, 4, 7, 6, 2, 4, 0, 1
		};

		glGenBuffers( 3, mcc_buffers );
		glBindBuffer( GL_ARRAY_BUFFER, mcc_buffers[0] );
		glBufferData( GL_ARRAY_BUFFER, 8*3*sizeof(GLfloat), mcc_tab_vertices, GL_STATIC_DRAW );
		glBindBuffer( GL_ARRAY_BUFFER, mcc_buffers[1] );
		glBufferData( GL_ARRAY_BUFFER, 8*3*sizeof(GLfloat), mcc_tab_colors, GL_STATIC_DRAW );
		glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mcc_buffers[2] );
		glBufferData( GL_ELEMENT_ARRAY_BUFFER, 14*sizeof(GLuint), mcc_tab_indices, GL_STATIC_DRAW );



		glEnableVertexAttribArray( 0 );
		glEnableVertexAttribArray( 1 );
		glBindBuffer( GL_ARRAY_BUFFER, mcc_buffers[0] );
		glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
		glBindBuffer( GL_ARRAY_BUFFER, mcc_buffers[1] );
		glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, 0 );
		glBindBuffer( GL_ARRAY_BUFFER, mcc_buffers[2] );
		glDrawElements( GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_INT, 0 );
		glDisableVertexAttribArray( 0 );
		glDisableVertexAttribArray( 1 );
	}

};

#endif /* OGLCONTEXT_H_ */
